package com.zt.bigdata.spark.scala.chapter5

import scala.collection.mutable.ArrayBuffer

object Chapter5 extends App {
  //implicit 使用隐式能够减少代码，能够向已有的类型中注入新的方法
  def calcTax(amount: Float)(implicit rate: Float): Float = amount * rate

  implicit val currentTaxRate = 0.08f
  val tax = calcTax(50000F)
  println(tax)


  val list = MyList(List(1, 3, 5, 2, 4))
  list sortBy1 (i => -i) foreach println
  list sortBy2 (i => -i) foreach println


  val buffer: ArrayBuffer[Int] = ArrayBuffer(1, 2)
  buffer.+=(3)
  println(buffer)


  List(1, 3, 5, 2, 4).sortBy(i => -i) foreach println


}

case class MyList[A](list: List[A]) {
  def sortBy1[B](f: A => B)(implicit ordering: Ordering[B]): List[A] =
    list.sortBy(f)(ordering)

  def sortBy2[B: Ordering](f: A => B): List[A] =
    list.sortBy(f)(implicitly[Ordering[B]])
}

class A {

  implicit class MyList2(list: List[Int]) {
    def length2: Long = {
      list.length
    }
  }


  implicit class SayHiImpl(intValue: Int) {
    val value: Int = intValue

    def sayHi = println(s"Hi $value!")
  }

  def main(args: Array[String]): Unit = {
    val i: Int = 1
    i.sayHi
  }
}

object B {
  def main(args: Array[String]): Unit = {
    //1 使用场景一：隐式参数
    def sayHello(age: Int)(implicit name: String) = println("my name is:" + name + ",my age is:" + age)

    implicit val name = "zhangtong"
    sayHello(23)

    //使用场景二：类型匹配
    import scala.language.implicitConversions
    implicit def int2Range(num: Int): Range = 1 to num

    def spreadNum(range: Range): String = range.mkString(",")

    println(spreadNum(5))

    //使用场景三：类型增强
    implicit def man2SuperMan(man: Man): SuperMan = new SuperMan(man.name)

    val man = new Man("zhangtong")
    println(man.getClass)
    man.fly

    /**
      * 在scala2.10后提供了隐式类，可以使用implicit声明类，但是需要注意以下几点：
      * 1.其所带的构造参数有且只能有一个
      * 2.隐式类必须被定义在类，伴生对象和包对象里
      * 3.隐式类不能是case class（case class在定义会自动生成伴生对象与2矛盾）
      * 4.作用域内不能有与之相同名称的标示符
      *
      * @param man
      */
    implicit class MyImplicitTypeConversion(val man: Man) {
      def fly2 = println("you can fly")
    }
    //使用隐式类 隐式转换
    man.fly2

    //显示操作
    val myImplicitTypeConversion = new MyImplicitTypeConversion(man)
    myImplicitTypeConversion.fly2
  }
}


class Man(val name: String)

class SuperMan(val name: String) {
  def fly = println("you can fly")
}



